﻿//---------------------------------------------------------------------
// Author: Harley Green
//
// Description: Class to retrieve messages from a MSMQueue
//
// Creation Date: 2008/3/8
//---------------------------------------------------------------------

using System;
using System.Management.Automation;
using System.Messaging;

namespace Pscx.Commands.Messaging
{
    [Cmdlet(VerbsCommunications.Receive, PscxNouns.MSMQMessage,
        DefaultParameterSetName = "Named", SupportsShouldProcess = true)]
    public class ReceiveMSMQMessage : MessageQueueCmdlet
    {
        private int timeOut = 5;

        [Parameter]
        public SwitchParameter Peek { get; set; }

        [Parameter]
        public Type TargetType { get; set; }

        [Parameter]
        public int TimeOut
        {
            get { return timeOut; }
            set { timeOut = value; }
        }

        [Parameter]
        public IMessageFormatter Formatter
        {
            get;
            set;
        }

        protected override void ProcessRecord()
        {
            try
            {
                if (ShouldProcess(GetPath()))
                {
                    if (Exists)
                    {
                        using (var queue = GetQueue())
                        {
                            if (TargetType != null)
                            {
                                queue.Formatter = GetFormatter();
                            }
                            using (var message = GetMessage(queue))
                            {
                                if (message == null)
                                {
                                    return;
                                }
                                if (TargetType == null)
                                {
                                    WriteObject(message.Body);
                                }
                                else
                                {
                                    WriteObject(Convert.ChangeType(message.Body, TargetType));
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                WriteError(new ErrorRecord(e, "Receive-Message", ErrorCategory.ReadError, null));
            }
        }

        private IMessageFormatter GetFormatter()
        {
            return Formatter ?? new XmlMessageFormatter(new[] { TargetType });
        }

        private Message GetMessage(MessageQueue queue)
        {
            try
            {
                var timeSpan = new TimeSpan(0, 0, 0, timeOut);
                return Peek.IsPresent ? queue.Peek(timeSpan) : queue.Receive(timeSpan);
            }
            catch (MessageQueueException e)
            {
                if (e.Message == "Timeout for the requested operation has expired.")
                {
                    return null;
                }
                throw;
            }
        }
    }
}